package com.sh.data.engine.application.service.integration;

import com.sh.data.engine.application.model.dto.base.PagerResponse;
import com.sh.data.engine.application.model.dto.integration.*;
import com.sh.data.engine.application.model.mapper.integration.*;
import com.sh.data.engine.application.model.request.integration.*;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.ApiLogDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.JarUploadResultDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.TaskConfigDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.ExpressionParam;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.PreviewExpressParam;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.TaskConfigParam;
import com.sh.data.engine.domain.integration.api.webservice.model.domain.GetServiceDomain;
import com.sh.data.engine.domain.integration.api.webservice.model.domain.TaskDomain;
import com.sh.data.engine.domain.integration.api.webservice.model.domain.TaskOverviewDomain;
import com.sh.data.engine.domain.integration.api.webservice.model.domain.TestApiHttpDomain;
import com.sh.data.engine.domain.integration.api.webservice.model.param.ApiWsAuthParam;
import com.sh.data.engine.domain.integration.api.webservice.model.param.ApiWsRequestBodyParam;
import com.sh.data.engine.domain.integration.api.webservice.model.param.GetServiceParam;
import com.sh.data.engine.domain.integration.api.webservice.model.param.TestApiWsParam;
import com.sh.data.engine.domain.integration.api.webservice.service.ApiWsService;
import com.sh.data.engine.domain.integration.datasource.model.domain.DataSourceDomain;
import com.sh.data.engine.domain.shims.db.model.FieldInfoDomain;
import com.sh.data.engine.domain.shims.db.model.TableInfoDomain;
import com.sh.data.engine.domain.util.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Objects;

/**
 * @author: mengzheng.mhc
 * @date: 2024/6/28 14:48
 */
@Slf4j
@Service
public class ApiWsApplicationService {

    @Autowired
    private ApiWsService apiWsService;

    @Autowired
    private WsTaskOverviewDTOMapper wsTaskOverviewDTOMapper;

    @Autowired
    private TaskItemDTOPageMapper taskItemDTOPageMapper;

    @Autowired
    private WsTaskDTOMapper wsTaskDTOMapper;

    @Autowired
    private UploadJarDTOMapper uploadJarDTOMapper;

    public TaskOverviewDTO getOverview(Long projectId) {
        TaskOverviewDomain overview = apiWsService.getOverview(projectId);
        return wsTaskOverviewDTOMapper.map(overview);
    }

    public PagerResponse<TaskItemDTO> getTaskPage(Integer pageNum, Integer pageSize, Integer status, String search) {
        var pageResult = apiWsService.getTaskPage(pageNum, pageSize, status, search);
        return taskItemDTOPageMapper.toPageResponse(pageResult);
    }

    public WsTaskDTO getTaskById(Long id) {
        TaskDomain taskDomain = apiWsService.getTaskById(id);
        WsTaskDTO wsTaskDTO = wsTaskDTOMapper.map(taskDomain);
        TaskDomain.TestAPiWsRequest sourceApiWsRequest = taskDomain.getApiWsRequest();
        TestApiWsRequest testApiWsRequest =
            ConvertUtil.copyProperties(sourceApiWsRequest, TestApiWsRequest.class);
        testApiWsRequest.setApiWsAuthParam(
            ConvertUtil.copyProperties(
                sourceApiWsRequest.getApiWsAuthParam(), TestApiWsRequest.ApiHttpAuthParam.class));
        //    // 请求头
        //    TestApiWsRequest.ApiHttpRequestHeaderParam apiHttpRequestHeaderParam =
        //        new TestAPiHttpRequest.ApiHttpRequestHeaderParam();
        //    if (null != sourceApiHttpRequest.getApiHttpRequestHeaderParam()) {
        //      apiHttpRequestHeaderParam.setParams(
        //          ConvertUtil.copyProperties(
        //              sourceApiHttpRequest.getApiHttpRequestHeaderParam().getParams(),
        //              TestAPiHttpRequest.ApiHttpRequestHeaderParam.Header.class));
        //    }
        //    testAPiHttpRequest.setApiHttpRequestHeaderParam(apiHttpRequestHeaderParam);

        // 请求体
        testApiWsRequest.setApiWsRequestBodyParam(
            ConvertUtil.copyProperties(
                sourceApiWsRequest.getApiWsRequestBodyParam(),
                TestApiWsRequest.ApiHttpRequestBodyParam.class));
        wsTaskDTO.setApiWsRequest(testApiWsRequest);

        TaskDomain.PreviewExpressRequest sourcePreviewExpressRequest =
            taskDomain.getPreviewExpressRequest();
        PreviewExpressRequest previewExpressRequest =
            ConvertUtil.copyProperties(sourcePreviewExpressRequest, PreviewExpressRequest.class);
        previewExpressRequest.setExpressionParamList(
            ConvertUtil.copyProperties(
                sourcePreviewExpressRequest.getExpressionParamList(),
                PreviewExpressRequest.ExpressionParam.class));
        wsTaskDTO.setPreviewExpressRequest(previewExpressRequest);

        TaskConfigDomain sourceTaskConfigRequest = taskDomain.getTaskConfigRequest();
        WsTaskDTO.TaskConfigRequest taskConfigRequest =
            ConvertUtil.copyProperties(sourceTaskConfigRequest, WsTaskDTO.TaskConfigRequest.class);
        // 给前端回显返回值left pad 0
        wsTaskDTO.setTaskConfigRequest(taskConfigRequest);

        taskConfigRequest.setTargetFields(
            ConvertUtil.copyProperties(
                sourceTaskConfigRequest.getTargetFields(),
                WsTaskDTO.TaskConfigRequest.TargetField.class));
        taskConfigRequest.setFieldMappings(
            ConvertUtil.copyProperties(
                sourceTaskConfigRequest.getFieldMappings(),
                WsTaskDTO.TaskConfigRequest.FieldMapping.class));
        taskConfigRequest.setPartitions(
            ConvertUtil.copyProperties(
                sourceTaskConfigRequest.getPartitions(),
                WsTaskDTO.TaskConfigRequest.PartitionField.class));
        wsTaskDTO.setTaskConfigRequest(taskConfigRequest);
        return wsTaskDTO;
    }

    public boolean saveTask(SaveWsTaskRequest saveTaskRequest) {
        TestApiWsRequest apiHttpRequest = saveTaskRequest.getApiWsRequest();
        // 参数转换 请求参数
        TestApiWsParam testApiWsParam =
            ConvertUtil.copyProperties(apiHttpRequest, TestApiWsParam.class);

        // 复制认证参数
        ApiWsAuthParam apiWsAuthParam =
            ConvertUtil.copyProperties(apiHttpRequest.getApiWsAuthParam(), ApiWsAuthParam.class);
        testApiWsParam.setApiWsAuthParam(apiWsAuthParam);

        // ws 没有请求头
        //    if (null != apiHttpRequest.getApiHttpRequestHeaderParam()) {
        //      ApiHttpRequestHeaderParam apiHttpRequestHeaderParam =
        //          new ApiHttpRequestHeaderParam(
        //              ConvertUtil.copyProperties(
        //                  apiHttpRequest.getApiHttpRequestHeaderParam().getParams(),
        //                  ApiHttpRequestHeaderParam.Header.class));
        //      testApiWsParam.setApiHttpRequestHeaderParam(apiHttpRequestHeaderParam);
        //    }

        // 如果请求体设置了x-www-form-urlencoded, 进行复制
        TestApiWsRequest.ApiHttpRequestBodyParam sourceBodyParam =
            apiHttpRequest.getApiWsRequestBodyParam();
        ApiWsRequestBodyParam apiWsRequestBodyParam =
            ConvertUtil.copyProperties(sourceBodyParam, ApiWsRequestBodyParam.class);
        if (Objects.equals("application/x-www-form-urlencoded", sourceBodyParam.getContentType())) {
            if (CollectionUtils.isNotEmpty(sourceBodyParam.getFormParams())) {
                apiWsRequestBodyParam.setFormParams(
                    ConvertUtil.copyProperties(
                        testApiWsParam.getApiWsRequestBodyParam().getFormParams(),
                        ApiWsRequestBodyParam.FormParam.class));
            }
        }
        String jsonBody = apiWsRequestBodyParam.getBody();
        if (StringUtils.isNotEmpty(jsonBody)) {
            apiWsRequestBodyParam.setBody(jsonBody.replace("\r\n", ""));
        }
        testApiWsParam.setApiWsRequestBodyParam(apiWsRequestBodyParam);

        // 用户填写的js脚本或者json path
        PreviewExpressRequest previewExpressRequest = saveTaskRequest.getPreviewExpressRequest();
        boolean existJsScript = StringUtils.isNotBlank(previewExpressRequest.getJsScript());
        boolean existJsonPath =
            CollectionUtils.isNotEmpty(previewExpressRequest.getExpressionParamList());
        if (existJsScript == existJsonPath) {
            throw new BusinessException("js脚本和json path必须填写并且只能填写一个");
        }
        PreviewExpressParam previewExpressParam =
            ConvertUtil.copyProperties(previewExpressRequest, PreviewExpressParam.class);
        // 如果填写的是jsonpath,进行复制
        if (existJsonPath) {
            previewExpressParam.setExpressionParamList(
                ConvertUtil.copyProperties(
                    previewExpressRequest.getExpressionParamList(), ExpressionParam.class));
        }

        // 任务其他配置
        TaskConfigRequest taskConfigRequest = saveTaskRequest.getTaskConfigRequest();
        TaskConfigParam taskConfigParam =
            ApiTaskConfigConvert.convertTaskConfigParam(taskConfigRequest);

        apiWsService.save(
            saveTaskRequest.getId(),
            saveTaskRequest.getTaskName(),
            testApiWsParam,
            previewExpressParam,
            taskConfigParam);

        return true;
    }

    public Long reRunTask(Long taskId) {
        return apiWsService.run(taskId);
    }

    public boolean offlineTask(Long taskId) {
        apiWsService.operate(taskId, "offline");
        return true;
    }

    public boolean publishTask(Long taskId) {
        apiWsService.operate(taskId, "online");
        return true;
    }

    public boolean deleteTask(Long taskId) {
        apiWsService.delete(taskId);
        return true;
    }

    public GetServiceDTO getWsdlPortsAndMethods(GetServiceRequest getServiceRequest) {
        GetServiceParam getServiceParam =
            ConvertUtil.copyProperties(getServiceRequest, GetServiceParam.class);
        GetServiceDomain wsdlPortsAndMethods = apiWsService.getWsdlPortsAndMethods(getServiceParam);
        return ConvertUtil.copyProperties(wsdlPortsAndMethods, GetServiceDTO.class);
    }

    public TestApiDTO test(TestApiWsRequest testApiWsRequest) {
        TestApiWsParam testApiWsParam =
            ConvertUtil.copyProperties(testApiWsRequest, TestApiWsParam.class);
        // 复制认证信息
        testApiWsParam.setApiWsAuthParam(
            ConvertUtil.copyProperties(testApiWsRequest.getApiWsAuthParam(), ApiWsAuthParam.class));
        // 复制请求体
        testApiWsParam.setApiWsRequestBodyParam(
            ConvertUtil.copyProperties(
                testApiWsRequest.getApiWsRequestBodyParam(), ApiWsRequestBodyParam.class));
        TestApiHttpDomain testApiHttpDomain = apiWsService.testApi(testApiWsParam);
        return ConvertUtil.copyProperties(testApiHttpDomain, TestApiDTO.class);
    }

    public UploadJarDTO uploadJar(MultipartFile file) {
        JarUploadResultDomain jarUploadResultDomain = apiWsService.uploadJar(file);
        return uploadJarDTOMapper.map(jarUploadResultDomain);
    }

    public List<List<Object>> preview(PreviewExpressRequest previewExpressRequest) {
        boolean existJsScript = StringUtils.isNotBlank(previewExpressRequest.getJsScript());
        boolean existJsonPath =
            CollectionUtils.isNotEmpty(previewExpressRequest.getExpressionParamList());
        if (existJsScript == existJsonPath) {
            throw new BusinessException("js脚本和json path必须填写并且只能填写一个");
        }
        PreviewExpressParam previewExpressParam =
            ConvertUtil.copyProperties(previewExpressRequest, PreviewExpressParam.class);
        if (existJsonPath) {
            List<ExpressionParam> expressionParams =
                ConvertUtil.copyProperties(
                    previewExpressRequest.getExpressionParamList(), ExpressionParam.class);
            previewExpressParam.setExpressionParamList(expressionParams);
        }
        List<List<Object>> preview = apiWsService.preview(previewExpressParam);
        return preview;
    }

    public GetDataSourceDTO getDatabases(Long projectId) {
        List<DataSourceDomain> databases = apiWsService.getDatabases(projectId);
        var getDataSourceDTO = new GetDataSourceDTO();
        List<GetDataSourceDTO.DataSource> dataSources =
            ConvertUtil.copyProperties(databases, GetDataSourceDTO.DataSource.class);
        getDataSourceDTO.setDataSources(dataSources);
        return getDataSourceDTO;
    }

    public GetTargetTablesDTO getTargetTables(Long dsId) {
        List<TableInfoDomain> targetTables = apiWsService.getTargetTables(dsId);
        GetTargetTablesDTO getTargetTablesDTO = new GetTargetTablesDTO();
        List<GetTargetTablesDTO.Table> tables =
            ConvertUtil.copyProperties(targetTables, GetTargetTablesDTO.Table.class);
        for (GetTargetTablesDTO.Table table : tables) {
            if (StringUtils.isNotEmpty(table.getSchema())) {
                table.setDetailedTblName(String.format("%s.%s", table.getSchema(), table.getTableName()));
            }
        }
        getTargetTablesDTO.setTables(tables);
        return getTargetTablesDTO;
    }

    public GetCreateTableDDLDTO getCreateTableDDL(GetCreateTableDDLRequest getCreateTableDDLRequest) {
        Long projectId = ServletUtils.getProjectId();
        String createTableDDL =
            apiWsService.getCreateTableDDL(
                projectId,
                getCreateTableDDLRequest.getDsId(),
                getCreateTableDDLRequest.getFields(),
                getCreateTableDDLRequest.getIsSupportRtf());
        return new GetCreateTableDDLDTO(createTableDDL);
    }

    public String saveTargetTable(SaveTargetTableRequest saveTargetTableRequest) {
        Long projectId = ServletUtils.getProjectId();
        return apiWsService.saveTargetTable(
            projectId, saveTargetTableRequest.getSql(), saveTargetTableRequest.getDataSecretId());
    }

    public GetFieldsDTO getTargetTableFields(Long dsId, String tableName) {
        List<FieldInfoDomain> targetTableFields = apiWsService.getTargetTableFields(dsId, tableName);
        GetFieldsDTO getFieldsResponse = new GetFieldsDTO();
        getFieldsResponse.setFields(
            ConvertUtil.copyProperties(targetTableFields, GetFieldsDTO.Field.class));
        return getFieldsResponse;
    }

    public ApiHttpLogDTO getOfflineSyncLog(Long logId, Integer offset) {
        ApiLogDomain logDomain = apiWsService.getOfflineSyncLog(logId, offset);
        return ConvertUtil.copyProperties(logDomain, ApiHttpLogDTO.class);
    }

    public boolean stopTask(Long logId) {
        apiWsService.stop(logId);
        return true;
    }
}
